#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：turbo 
@File    ：apifields.py
@Author  ：赵加响
@Date    ：2024/5/17 10:58 
@Desc    ：
"""
from rest_framework import serializers

from apps.rbac.models import MenuSensitiveField, SensitiveField, UserMenuSensitiveField
from bases import messages


class ApiDecimalField(serializers.DecimalField):
    """
    解决原生DRF默认将DecimalField在Json中输出为字符串
    """

    def to_representation(self, value):
        if value == int(value):
            return int(value)
        return round(float(value), self.decimal_places)


class SensitiveValueMixin:
    """
    敏感数据混入
    """

    def __init__(self):
        self.model = None
        self.request = None

    def representation(self, value):
        if self.tag is not None:
            self.model = self.parent.Meta.model
            request = self.context.get('request', None)
            user = request.user
            if user.is_admin():
                return value
            else:
                menu_id = request.session.get('menu_id')
                try:
                    menu_sensitive_field = MenuSensitiveField.objects.get(menu__id=menu_id,
                                                                          sensitive_field__code__exact=self.tag)

                    user_menu_sensitive_field = UserMenuSensitiveField.objects.get(user=user,
                                                                                   menu_sensitive_field=menu_sensitive_field)

                    if user_menu_sensitive_field.has_read_permission():
                        return value
                    else:
                        return None
                except (MenuSensitiveField.DoesNotExist, UserMenuSensitiveField.DoesNotExist):
                    return None
        return value

    def has_write_permission(self):
        if self.tag is not None:
            self.model = self.parent.Meta.model
            request = self.context.get('request', None)
            user = request.user
            if user.is_admin():
                return True
            else:
                menu_id = request.session.get('menu_id')
                try:
                    menu_sensitive_field = MenuSensitiveField.objects.get(menu__id=menu_id,
                                                                          sensitive_field__code__exact=self.tag)

                    user_menu_sensitive_field = UserMenuSensitiveField.objects.get(user=user,
                                                                                   menu_sensitive_field=menu_sensitive_field)

                    if user_menu_sensitive_field.has_write_permission():
                        return True
                    else:
                        return False
                except (MenuSensitiveField.DoesNotExist, UserMenuSensitiveField.DoesNotExist):
                    return False
        return True


class ApiSensitiveDecimalField(serializers.DecimalField, SensitiveValueMixin):
    """
    敏感Decimal字段，使用属性tag时，则对该字段进行敏感字段权限验证，不使用属性tag则和普通字段一样
    使用方式：ApiSensitiveDecimalField(..., tag='AMOUNT')
    """

    def __init__(self, **kwargs):
        self.tag = kwargs.pop('tag', None)
        # 如果该tag存在值，则该字段为必输项
        if self.tag is not None:
            assert SensitiveField.objects.filter(code__exact=self.tag, field_type__exact='D').exists(), (
                f'tag({self.tag})必须在SensitiveField中定义，且类型为DecimalField')
            kwargs['required'] = True
            kwargs['allow_null'] = False
        super().__init__(**kwargs)

    def to_representation(self, value):
        value = self.representation(value)
        if value is not None:
            if value == int(value):
                return int(value)
            return round(float(value), self.decimal_places)
        return None

    def to_internal_value(self, value):
        if not self.has_write_permission():
            raise serializers.ValidationError(messages.MSG_50006_PERMISSION_DENIED)

        return super().to_internal_value(value)


class ApiSensitiveCharField(serializers.CharField, SensitiveValueMixin):
    """
    敏感Char字段，使用属性tag时，则对该字段进行敏感字段权限验证，不使用属性tag则和普通字段一样
    使用方式：ApiSensitiveCharField(..., tag='CURRENCY')
    """

    def __init__(self, **kwargs):
        self.tag = kwargs.pop('tag', None)
        # 如果该tag存在值，则该字段为必输项
        if self.tag is not None:
            assert SensitiveField.objects.filter(code__exact=self.tag, field_type__exact='C').exists(), (
                f'tag({self.tag})必须在SensitiveField中定义，且类型为CharField')
            kwargs['required'] = True
            kwargs['allow_null'] = False
            kwargs['allow_blank'] = False
        super().__init__(**kwargs)

    def to_representation(self, value):
        return self.representation(value)

    def to_internal_value(self, value):
        if not self.has_write_permission():
            raise serializers.ValidationError(messages.MSG_50006_PERMISSION_DENIED)

        return super().to_internal_value(value)
